/**
 * Project: shuyin-sync
 * 
 * File Created at Mar 23, 2012
 * $Id$
 * 
 * Copyright 2008 6677bank.com Croporation Limited.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * 6677bank Company. ("Confidential Information").  You shall not
 * disclose such Confidential Information and shall use it only in
 * accordance with the terms of the license agreement you entered into
 * with 6677bank.com.
 */
package com.bank6677.sync.csm.helper;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.bank6677.application.Constants;
import com.bank6677.common.exception.BusinessException;

/**
 * 申请单相关帮助类
 * 
 * @author liyue
 * @version ApplicationHelper.java Mar 23, 2012 2:21:03 PM
 */
public class ApplicationHelper {

    private final static Map<FormCategory, Form>   allForms            = new HashMap<FormCategory, Form>();  //key为老表单类型

    private final static Map<String, String>       statusMapping       = new HashMap<String, String>();

    private final static Map<String, String>       operationMapping    = new HashMap<String, String>();

    private static final Map<String, List<String>> syncProperties      = new HashMap<String, List<String>>();

    private static final String                    SPLIT_SYNC_PROPERTY = "|";

    /**
     * 根据老的贷款类型和贷款用途得到表类型id
     * 
     * @param loanType
     * @param loanPurpose
     * @return
     */
    public static String getNewTableName(Integer loanType, Integer loanPurpose) {
        Form form = allForms.get(new FormCategory(loanType, loanPurpose));
        return form.getTableName();
    }

    /**
     * 根据老的贷款类型和贷款用途得到模块id串
     * 
     * @param loanType
     * @param loanPurpose
     * @return
     */
    public static String getNewModelIds(Integer loanType, Integer loanPurpose) {
        Form form = allForms.get(new FormCategory(loanType, loanPurpose));
        return form.getModelIds();
    }

    /**
     * 根据老的贷款类型和贷款用途得到新贷款类型
     * 
     * @param loanType
     * @param loanPurpose
     * @return
     */
    public static Integer getNewLoanType(Integer loanType, Integer loanPurpose) {
        Form form = allForms.get(new FormCategory(loanType, loanPurpose));
        return form.getNewCategory().getLoanType();
    }

    /**
     * 根据老的贷款类型和贷款用途得到新贷款主体
     * 
     * @param loanType
     * @param loanPurpose
     * @return
     */
    public static Integer getNewLoanSubject(Integer loanType, Integer loanPurpose) {
        Form form = allForms.get(new FormCategory(loanType, loanPurpose));
        return form.getNewCategory().getLoanSubject();
    }

    /**
     * 根据老的贷款类型和贷款用途得到新贷款用途
     * 
     * @param loanType
     * @param loanPurpose
     * @return
     */
    public static Integer getNewLoanPurpose(Integer loanType, Integer loanPurpose) {
        Form form = allForms.get(new FormCategory(loanType, loanPurpose));
        return form.getNewCategory().getLoanPurpose();
    }

    /**
     * <p>
     * Returns new process status.
     * 
     * @param oldStatus
     * @return
     */
    public static String getNewProcessStatus(String oldStatus) {
        return statusMapping.get(oldStatus);
    }

    /**
     * <p>
     * Returns new pro status. If oldStatus is not in statusMapping's key set,
     * returns "99"
     * 
     * <pre>
     * ApplicationHelper.getNewProStatus(&quot;0221&quot;) = &quot;02&quot;;
     * ApplicationHelper.getNewProStatus(&quot;0321&quot;) = &quot;03&quot;;
     * ApplicationHelper.getNewProStatus(&quot;03&quot;) = &quot;99&quot;;
     * </pre>
     * 
     * @param oldStatus
     * @return
     */
    public static String getNewProStatus(String oldStatus) {
        String processStat = statusMapping.get(oldStatus);
        if (StringUtils.isNotBlank(processStat) && processStat.length() > 2) {
            return processStat.substring(0, 2);
        }
        return "99";
    }

    /**
     * <p>
     * Returns new operation log tag.
     * 
     * @param oldOperation
     * @return
     */
    public static String getNewOperation(String oldOperation) {
        return operationMapping.get(oldOperation);
    }

    /**
     * <p>
     * Returns new reservation status.
     * 
     * @param oldStatus
     * @return
     */
    public static String getNewReservationStatus(String oldStatus) {
        if ("1".equals(oldStatus)) {
            return "0";
        } else {
            return "1";
        }
    }

    /**
     * @param name
     * @param oldValue
     * @return
     */
    public static String getPropertyValueInAppExt(String name, String oldValue) {
        List<String> values = syncProperties.get(name);
        for (String value : values) {
            if (StringUtils.startsWithIgnoreCase(value, oldValue + SPLIT_SYNC_PROPERTY)) {
                return StringUtils.substringAfter(value, oldValue + SPLIT_SYNC_PROPERTY);
            }
        }
        return null;
    }

    public static void main(String[] args) {
        //        syncProperties.put("tradeType", CollectionUtils.arrayToList(new String[] { "1-2", "2-3", "3-4" }));
        getSyncPropertiesXml("synchronize-ext.xml");
        System.out.println(getPropertyValueInAppExt("workActor", "2"));
    }

    /**
     * <p>
     * Read the <code>formInfo.xml</code> file and return application form
     * information.
     * 
     * @return String[]{tableName, modelIds, oldCategory, newCategory}
     */
    static List<String[]> getFormInfoFromXml() {
        InputStream ins = ApplicationHelper.class.getClassLoader().getResourceAsStream("formInfo.xml");
        SAXReader saxReader = new SAXReader();
        List<String[]> formInfos = new ArrayList<String[]>();
        try {
            Document doc = saxReader.read(ins);
            Element forms = doc.getRootElement();
            ;
            for (Object obj : forms.elements()) {
                Element element = (Element) obj;
                String[] formInfo = new String[] { element.attributeValue("tableName"), element.attributeValue("modelIds"),
                        element.attributeValue("oldCategory"), element.attributeValue("newCategory") };
                formInfos.add(formInfo);
            }

        } catch (DocumentException e) {
            throw new BusinessException(e.getMessage(), e);
        } finally {
        }
        return formInfos;
    }

    static void getSyncPropertiesXml(String fileName) {
        InputStream ins = ApplicationHelper.class.getClassLoader().getResourceAsStream("sync/" + fileName);
        SAXReader saxReader = new SAXReader();

        try {
            Document doc = saxReader.read(ins);
            Element properties = doc.getRootElement();
            for (Object obj : properties.elements()) {
                Element property = (Element) obj;
                List<String> valueList = new ArrayList<String>();
                for (Object obj2 : property.elements()) {
                    Element value = (Element) obj2;
                    String values = value.attributeValue("from") + SPLIT_SYNC_PROPERTY
                            + (StringUtils.isBlank(value.attributeValue("to")) ? null : value.attributeValue("to"));
                    valueList.add(values);
                }
                syncProperties.put(property.attributeValue("name"), valueList);
            }
        } catch (DocumentException e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    /**
     * <p>
     * Returns the FormCategory using given values <code>categoryValues</code>.
     * pattern like "subject, category, usage"
     * 
     * @param categoryValues
     * @return
     */
    private static FormCategory packageFormCategory(String categoryValues) {
        if (StringUtils.isBlank(categoryValues)) {
            throw new BusinessException(" package FormCategory entity, values is null or empty.");
        }
        if (StringUtils.countMatches(categoryValues, ",") < 2) {
            throw new BusinessException(" package FormCategory entity, \',\' in paramater must be two. value:" + categoryValues);
        }
        String[] categoryValuesArray = categoryValues.split(",");
        FormCategory category = new FormCategory(StringUtils.isBlank(categoryValuesArray[0]) ? null : new Integer(categoryValuesArray[0]),
                new Integer(categoryValuesArray[1]), new Integer(categoryValuesArray[2]));
        return category;
    }

    static {
        /////   初始化所有表单信息  allForms   //////
        List<String[]> forms = getFormInfoFromXml();
        for (String[] values : forms) {
            allForms.put(packageFormCategory(values[2]), new Form(values[0], values[1], packageFormCategory(values[2]),
                    packageFormCategory(values[3])));
        }

        /////   初始化需同步项常量         /////
        getSyncPropertiesXml("synchronize-ext.xml");

        /////   初始化所有流程状态信息  statusMapping   /////
        statusMapping.put("-1", Constants.PROCESS_STAT_KF_PASS_DROP);
        statusMapping.put("-2", Constants.PROCESS_STAT_KF_PASS_DROP);
        statusMapping.put("-3", Constants.PROCESS_STAT_KF_PASS_DROP);
        statusMapping.put("0", Constants.PROCESS_STAT_NOT_HANDLE_APPLICATION);
        statusMapping.put("f", Constants.PROCESS_STAT_HANDLING_APPLICATION);
        statusMapping.put("9", Constants.PROCESS_STAT_NOT_COMMIT_APPLY);
        statusMapping.put("10", Constants.PROCESS_STAT_NOT_COMMIT_APPLY);
        statusMapping.put("x", Constants.PROCESS_STAT_NOT_COMMIT_ATTACHMENT);
        statusMapping.put("w", Constants.PROCESS_STAT_WAITING_VERIFY);
        statusMapping.put("8", Constants.PROCESS_STAT_RESERVE);
        statusMapping.put("i", Constants.PROCESS_STAT_NOT_PASS_VERIFY);
        statusMapping.put("a", Constants.PROCESS_STAT_NOT_PASS_VERIFY);
        statusMapping.put("y", Constants.PROCESS_STAT_WAITING_SEND);
        statusMapping.put("h", Constants.PROCESS_STAT_WAITING_INSTITUTION_VERIFY);
        statusMapping.put("c", Constants.PROCESS_STAT_WAITING_SEND);
        statusMapping.put("u", Constants.PROCESS_STAT_WAITING_INSTITUTION_CONFIRM);
        statusMapping.put("e", Constants.PROCESS_STAT_WAITING_CUSTOM_CONFIRM);
        statusMapping.put("b", Constants.PROCESS_STAT_KF_PASS_DROP);
        statusMapping.put("2", Constants.PROCESS_STAT_KF_PASS_DROP); //add by liyue 4.10.2012 cause have '2' in historic database 
        statusMapping.put("v", Constants.PROCESS_STAT_KF_PASS_DROP);
        statusMapping.put("z", Constants.PROCESS_STAT_PASS_DROP);
        statusMapping.put("d", Constants.PROCESS_STAT_NOT_PASS_DROP);
        statusMapping.put("k", Constants.PROCESS_STAT_WAITING_INSTITUTION_VERIFY);
        statusMapping.put("m", Constants.PROCESS_STAT_WAITING_INSTITUTION_SIGN);
        statusMapping.put("o", Constants.PROCESS_STAT_WAITING_INSTITUTION_LOANS);
        statusMapping.put("q", Constants.PROCESS_STAT_INSTITUTION_NOT_REPLY);
        statusMapping.put("s", Constants.PROCESS_STAT_INSTITUTION_NOT_REPLY);
        statusMapping.put("g", Constants.PROCESS_STAT_INSTITUTION_REFUSE);
        statusMapping.put("l", Constants.PROCESS_STAT_INSTITUTION_REFUSE);
        statusMapping.put("n", Constants.PROCESS_STAT_INSTITUTION_VERIFY_REFUSE);
        statusMapping.put("p", Constants.PROCESS_STAT_INSTITUTION_SIGN_REFUSE);
        statusMapping.put("r", Constants.PROCESS_STAT_INSTITUTION_LOANS_REFUSE);
        statusMapping.put("t", Constants.PROCESS_STAT_INSTITUTION_NOT_REPLY);
        statusMapping.put("6", Constants.PROCESS_STAT_REPLIED);
        statusMapping.put("7", Constants.PROCESS_STAT_KF_PASS_DROP);
        statusMapping.put("5", Constants.PROCESS_STAT_CUSTOM_STOP);
        statusMapping.put("j", Constants.PROCESS_STAT_CUSTOM_REFUSE);

        /////////////   日志类型        /////////
        operationMapping.put("1", com.bank6677.application.log.Constants.ACCOUNT_MANAGER_DROPAPP);
        operationMapping.put("2", com.bank6677.application.log.Constants.DS_SUBMIT);
        operationMapping.put("3", com.bank6677.application.log.Constants.ACCOUNT_MANAGER_DROPAPP_SUCCESS);
        operationMapping.put("4", com.bank6677.application.log.Constants.DS_GIVEUP_SUCCESS);
        operationMapping.put("5", com.bank6677.application.log.Constants.DS_RETURN);
        operationMapping.put("6", com.bank6677.application.log.Constants.END_APPLICATION);
        operationMapping.put("7", com.bank6677.application.log.Constants.DS_GIVEUP_SUCCESS);
        operationMapping.put("8", com.bank6677.application.log.Constants.PF_BACK_REVIEW);
        operationMapping.put("9", com.bank6677.application.log.Constants.DS_GIVEUP_FAILURE);
        operationMapping.put("10", com.bank6677.application.log.Constants.DS_SUBMIT);
        operationMapping.put("11", com.bank6677.application.log.Constants.KH_COMFIRM);
        operationMapping.put("12", com.bank6677.application.log.Constants.DS_GIVEUP_SUCCESS);
        operationMapping.put("13", com.bank6677.application.log.Constants.ACCOUNT_MANAGER_SAVE);
        operationMapping.put("14", com.bank6677.application.log.Constants.NEW_APPLICATION_ASSIGN);
        operationMapping.put("15", com.bank6677.application.log.Constants.pf_SEND_AGENT);
        operationMapping.put("16", com.bank6677.application.log.Constants.ACCOUNT_MANAGER_RESERVATION);
        //        operationMapping.put("17", com.bank6677.application.log.Constants.ACCOUNT_MANAGER_DROPAPP);
        //        operationMapping.put("18", com.bank6677.application.log.Constants.ACCOUNT_MANAGER_DROPAPP);
        //        operationMapping.put("19", com.bank6677.application.log.Constants.ACCOUNT_MANAGER_DROPAPP);
        operationMapping.put("20", com.bank6677.application.log.Constants.KH_REFUSE);

    }

    /**
     * <p>
     * Returns <code>true</code> if form fits the parameters, if not returns
     * <code>false</code>
     * 
     * @param loanType
     * @param loanPurpose
     * @return
     */
    public static boolean checkOldTypeAndPurpose(Integer loanType, Integer loanPurpose) {
        return allForms.get(new FormCategory(loanType, loanPurpose)) == null ? false : true;
    }

    public static boolean checkLinkMan(String name) {
        String[] excludeNames = new String[] { "test", "数银", "测试" };
        for (String excludeName : excludeNames) {
            
            if(name == null){
                return true;
            }
            
            if(name != null && StringUtils.contains(name, excludeName)){
                return true;
            } 
        }
        if (NumberUtils.isNumber(name)) {
            return true;
        }
        if (StringUtils.isBlank(name)) {
            return true;
        }
        if (StringUtils.containsAny(name, new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' })) {
            return true;
        }
        return false;
    }

    public static boolean checkPhone(String phone) {
        String[] excludePhones = new String[] { "13958058749" };
        for (String excludePhone : excludePhones) {
            return StringUtils.equals(excludePhone, phone);
        }
        if (StringUtils.isBlank(phone)) {
            return true;
        }
        return false;
    }

}

class Form {

    private String       tableName;  //表id
    private String       modelIds;   //模块ids
    private FormCategory oldCategory; //老系统表单类型
    private FormCategory newCategory; //新系统表单类型

    public Form() {
    }

    public Form(String tableName, String modelIds, FormCategory oldCategory, FormCategory newCategory) {
        this.tableName = tableName;
        this.modelIds = modelIds;
        this.oldCategory = oldCategory;
        this.newCategory = newCategory;
    }

    /**
     * @return the tableName
     */
    public String getTableName() {
        return tableName;
    }

    /**
     * @param tableName the tableName to set
     */
    public void setTableName(String tableName) {
        this.tableName = tableName;
    }

    /**
     * @return the oldCategory
     */
    public FormCategory getOldCategory() {
        return oldCategory;
    }

    /**
     * @param oldCategory the oldCategory to set
     */
    public void setOldCategory(FormCategory oldCategory) {
        this.oldCategory = oldCategory;
    }

    /**
     * @return the newCategory
     */
    public FormCategory getNewCategory() {
        return newCategory;
    }

    /**
     * @param newCategory the newCategory to set
     */
    public void setNewCategory(FormCategory newCategory) {
        this.newCategory = newCategory;
    }

    /**
     * @return the modelIds
     */
    public String getModelIds() {
        return modelIds;
    }

    /**
     * @param modelIds the modelIds to set
     */
    public void setModelIds(String modelIds) {
        this.modelIds = modelIds;
    }

}

/**
 * 表单类型
 * 
 * @author liyue
 */
class FormCategory {

    private Integer loanSubject; //贷款主体
    private Integer loanType;   //贷款类型
    private Integer loanPurpose; //贷款

    public FormCategory() {
    }

    public FormCategory(Integer loanType, Integer loanPurpose) {
        this.loanType = loanType;
        this.loanPurpose = loanPurpose;
    }

    public FormCategory(Integer loanSubject, Integer loanType, Integer loanPurpose) {
        this.loanSubject = loanSubject;
        this.loanType = loanType;
        this.loanPurpose = loanPurpose;
    }

    /**
     * @return the loanSubject
     */
    public Integer getLoanSubject() {
        return loanSubject;
    }

    /**
     * @param loanSubject the loanSubject to set
     */
    public void setLoanSubject(Integer loanSubject) {
        this.loanSubject = loanSubject;
    }

    /**
     * @return the loanType
     */
    public Integer getLoanType() {
        return loanType;
    }

    /**
     * @param loanType the loanType to set
     */
    public void setLoanType(Integer loanType) {
        this.loanType = loanType;
    }

    /**
     * @return the loanPurpose
     */
    public Integer getLoanPurpose() {
        return loanPurpose;
    }

    /**
     * @param loanPurpose the loanPurpose to set
     */
    public void setLoanPurpose(Integer loanPurpose) {
        this.loanPurpose = loanPurpose;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof FormCategory) {
            if (((FormCategory) obj).getLoanType().equals(loanType) && ((FormCategory) obj).getLoanPurpose().equals(loanPurpose)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        if (loanType != null) {
            hash += loanType.hashCode();
        }
        if (loanPurpose != null) {
            hash += loanPurpose.hashCode();
        }
        if (loanSubject != null) {
            hash += loanSubject.hashCode();
        }
        return hash;
    }

}

class operation {

    private String beforeStatus;
    private String afterStatus;
    private String operationId;

    /**
     * @return the beforeStatus
     */
    public String getBeforeStatus() {
        return beforeStatus;
    }

    /**
     * @param beforeStatus the beforeStatus to set
     */
    public void setBeforeStatus(String beforeStatus) {
        this.beforeStatus = beforeStatus;
    }

    /**
     * @return the afterStatus
     */
    public String getAfterStatus() {
        return afterStatus;
    }

    /**
     * @param afterStatus the afterStatus to set
     */
    public void setAfterStatus(String afterStatus) {
        this.afterStatus = afterStatus;
    }

    /**
     * @return the operationId
     */
    public String getOperationId() {
        return operationId;
    }

    /**
     * @param operationId the operationId to set
     */
    public void setOperationId(String operationId) {
        this.operationId = operationId;
    }

}
